from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings

from oauth.models import OAuthQQUser
from oauth.utils import OAuthQQ
from users.models import User


class OAuthQQUserSerializer(serializers.ModelSerializer):
    """
    保存QQ用户序列化器
    """
    sms_code = serializers.CharField(label="短信验证码", write_only=True)
    access_token = serializers.CharField(label="操作凭证", write_only=True)
    token = serializers.CharField(read_only=True)
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')

    class Meta:
        model = User
        fields = ["mobile", "password", "sms_code", "access_token", "token",
                  "id", "username"]
        extra_kwargs = {
            "username": {
                "read_only": True
            },
            "password": {
                "write_only": True,
                "min_length": 8,
                "max_length": 20,
                "error_messages": {
                    "min_length": "仅允许8-20个字符的密码",
                    "max_length": "仅允许8-20个字符的密码",
                }
            }
        }

    def validate(self, attrs):
        # 校验access_token
        access_token = attrs["access_token"]
        openid = OAuthQQ.check_save_user_token(access_token)

        if not openid:
            raise serializers.ValidationError("无效的access_token")

        attrs["openid"] = openid

        # 校验短信验证码
        mobile = attrs["mobile"]
        sms_code = attrs["sms_code"]
        redis_conn = get_redis_connection("verify_codes")
        real_sms_code = redis_conn.get("sms_%s" % mobile)
        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError("短信验证码错误")

        # 查询用户是否存在
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            pass
        else:
            # 存在,检查密码
            password = attrs["password"]
            if not user.check_password(password):
                raise serializers.ValidationError("密码错误")
            attrs["user"] = user
        return attrs

    def create(self, validated_data):
        openid = validated_data["openid"]
        user = validated_data.get("user")  # user可能有也可能没有,通过get获取
        mobile = validated_data["mobile"]
        password = validated_data["password"]

        if not user:
            # 用户不存在,创建用户,绑定openid
            user = User.objects.create(username=mobile, mobile=mobile,
                                       password=password)
        # 用户存在,绑定,创建OAuthQQUser数据
        OAuthQQUser.objects.create(user=user, openid=openid)
        # 签发token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token
        # 向视图对象中补充user对象属性，以便在视图中使用user
        self.context['view'].user = user

        return user

